package com.orange.fastdfsjava.controller;

import com.orange.fastdfsjava.pojo.FastDfsFile;
import com.orange.fastdfsjava.pojo.PageBean;
import com.orange.fastdfsjava.utils.R;
import com.orange.fastdfsjava.service.FastDfsFileService;
import com.orange.fastdfsjava.service.FastDfsFileTypeService;
import com.orange.fastdfsjava.utils.FastDFSClient;
import lombok.extern.slf4j.Slf4j;
import org.csource.common.MyException;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.UUID;

@Slf4j
@RestController
@RequestMapping("/fastDFSFile")
public class FileServerController {

    @Resource
    private FastDfsFileService fastDfsFileService;

    @Resource
    private FastDfsFileTypeService fastDfsFileTypeService;

    @PostMapping("/upload")
    @ResponseBody
    public R upload(@RequestParam("file") MultipartFile file) throws IOException {
        //将文件先存储在web服务器上(本机),在调用fastDFS的client将文件上传到 fastDFS服务器
        FastDfsFile fastDFSFile = new FastDfsFile();

        String contentType = file.getContentType();
        //检验当前文件是否在上述集合中
        log.info("上传的文件类型为：{}", contentType);
        int count = fastDfsFileTypeService.selectByFileType(contentType);
        if (count < 1) {
            log.info("不支持此文件类型上传 : {}", contentType);
            return R.error().setCode(208).setMessage("不支持此文件类型上传 : " + contentType);
        }
        log.info("此文件类型为 : {}", contentType);
        fastDFSFile.setFileType(contentType);

        //文件原始名称
        String originalFilename = file.getOriginalFilename();
        log.info("原始文件名称 : {}", originalFilename);
        fastDFSFile.setFileName(originalFilename);

        //文件扩展名比如22.jpg
        String filenameExtension = StringUtils.getFilenameExtension(originalFilename);
        log.info("文件类型 = {}", filenameExtension);//jpg
        if (filenameExtension == null) {
            return R.error().setCode(208).setMessage("此文件没有文件扩展名");
        }
        fastDFSFile.setExt(filenameExtension);

        //新文件名称
        String fileName = UUID.randomUUID().toString().replace("-", "") + "." + filenameExtension;
        log.info("新文件名称 = {}", fileName);

        FastDfsFile fastDfsFile1 = FastDFSClient.upload(file, fastDFSFile);
        if (fastDfsFile1 != null) {
            fastDfsFileService.save(fastDfsFile1);
            Long id = fastDfsFileService.selectByFileId(fastDfsFile1.getFileId());
            fastDfsFile1.setId(id);
            return R.ok().setCode(200).setMessage("上传成功").data("fastDfsFile", fastDfsFile1);
        }
        return R.error().setCode(208).setMessage("上传失败");
    }

    //restful风格
    @DeleteMapping()
    public R delete(@RequestParam("id") Long id, @RequestParam("fileId") String fileId) throws MyException, IOException {
        Boolean result = FastDFSClient.delete(fileId);
        if (!result) {
            log.info("删除失败");
            return R.error().setCode(208).setMessage("删除失败");
        }
        int count = fastDfsFileService.deleteFastDfsFileById(id);
        if (count < 1) {
            log.info("删除失败");
            return R.error().setCode(208).setMessage("删除失败");
        }
        log.info("删除成功");
        return R.ok().setCode(200).setMessage("删除成功");
    }

    //下载请求方式一
    @GetMapping("/way1")
    public void downloadfile1(HttpServletResponse response, String fileId, String fileName) throws IOException, MyException {
        if (fileId == null) return;
        log.info("fileName = {}", fileName);

        response.setContentType("application/force-download;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.addHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes("gb2312"), "ISO-8859-1"));

        byte[] bytes = FastDFSClient.downloadFastFile(fileId);
        FileInputStream fis = null;
        log.info("fileId = {}", fileId);

        int len = 0;
        OutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            if (bytes == null) {
                return;
            }
            log.info("success");
            outputStream.write(bytes);
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    //下载请求方式二
    @GetMapping()
    public void downloadfile(HttpServletResponse response, String fileId, String fileName) throws IOException, MyException {
        if (fileId == null) return;
        log.info("fileName = {}", fileName);

        byte[] buffer = FastDFSClient.downloadFastFile(fileId);
        log.info("fileId = {}", fileId);

        // 设置响应头，指定文件名
        // 清空response
        response.reset();
        // 设置response的Header
        response.setCharacterEncoding("UTF-8");
        //Content-Disposition的作用：告知浏览器以何种方式显示响应返回的文件，用浏览器打开还是以附件的形式下载到本地保存
        //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
        // filename表示文件的默认名称，因为网络传输只支持URL编码的相关支付，因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
        response.addHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes("gb2312"), "ISO-8859-1"));
        //response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
        // 告知浏览器文件的大小
        response.addHeader("Content-Length", "" + buffer.length);
        log.info("Content-Length = {}", buffer.length);
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);//response.setContentType("application/octet-stream");
        response.getOutputStream().write(buffer);
        //OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
        //outputStream.write(buffer);
        //outputStream.flush();
    }

    @GetMapping("/getPageFastImg/{page}/{limit}")
    public R getPageFastImg(@PathVariable int page, @PathVariable int limit) {
        PageBean<FastDfsFile> pageBean = fastDfsFileService.findFastDfsFileByPage(page, limit);
        return R.ok().setCode(200).setMessage("查询成功").data("pageBean", pageBean);
    }
}
